import {
    FC, ReactNode, useCallback, useEffect, useRef
} from 'react';
import styles from './snake.module.less';

export interface SnakeProps {
    children?: ReactNode;
}
/**
 * 顶点着色器：用来描述顶点特性
 * 片元着色器：进行逐片元处理程序  计算获取颜色信息，片元可以理解为一个个像素
 */
const Snake: FC<SnakeProps> = () => {
    const canvasRef = useRef(null);

    const main = useCallback(async (canvas: HTMLCanvasElement) => {
        const gl = canvas.getContext('webgl');

        const VERTEX_SHADER_SOURCE = `
            attribute vec4 aPosition;
            void main() {
                gl_Position = aPosition;
                gl_PointSize = 10.0;
            }
        `;

        const FRAGMENT_SHADER_SOURCE = `
            precision mediump float;
            uniform vec4 uColor;
            void main() {
                gl_FragColor = uColor;
            }
        `;

        const verShader = gl.createShader(gl.VERTEX_SHADER);
        const fragShader = gl.createShader(gl.FRAGMENT_SHADER);

        gl.shaderSource(verShader, VERTEX_SHADER_SOURCE);
        gl.shaderSource(fragShader, FRAGMENT_SHADER_SOURCE);

        gl.compileShader(verShader);
        gl.compileShader(fragShader);

        const program = gl.createProgram();

        gl.attachShader(program, verShader);
        gl.attachShader(program, fragShader);

        gl.linkProgram(program);
        gl.useProgram(program);

        const aPosition = gl.getAttribLocation(program, 'aPosition');
        const uColor = gl.getUniformLocation(program, 'uColor');

        gl.uniform4f(uColor, 0.0, 0.0, 1.0, 1.0);

        let speed = 0.01;
        let direction = 'x';
        const points = [
            {
                x: 0.0,
                y: 0.0
            }
        ];

        const handleControl = (e) => {
            switch (e.keyCode) {
            case 37:
                // 左边
                direction = 'x';
                speed = -0.005;
                break;
            case 38:
                // 上
                direction = 'y';
                speed = 0.005;
                break;
            case 39:
                // 右
                direction = 'x';
                speed = 0.005;
                break;
            case 40:
                // 下
                direction = 'y';
                speed = -0.005;
                break;
            default:
                console.log(e.keyCode);
            }
        };

        const timer = setInterval(() => {
            for (let i = 0; i < points.length; i++) {
                const point = points[i];
                point[direction] += speed;
                gl.vertexAttrib2f(aPosition, point.x, point.y);
                gl.drawArrays(gl.POINTS, 0, 1);
            }
        }, 80);

        window.addEventListener('keydown', handleControl, false);

        return () => {
            if (timer) {
                clearInterval(timer);
            }
            window.removeEventListener('keydown', handleControl, false);
        };
    }, []);

    useEffect(() => {
        let removeEvent = null;
        if (canvasRef.current) {
            removeEvent = main(canvasRef.current);
        }

        return () => {
            if (typeof removeEvent === 'function') {
                removeEvent?.();
            }
        };
    }, [main]);

    return (
        <div className={styles.snake}>
            <canvas ref={canvasRef} width="600" height="600" />
        </div>
    );
};

export default Snake;
